#include <cassidriver/CASsiDriverE.h>

// ***********************************************************************

// class EDROOMTopContext

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CASsiDriver::EDROOMTopContext::EDROOMTopContext (CASsiDriver &act, int16_t & EDROOMpVarVByteNumber, bool_t & EDROOMpVarVMessageCompleted, byte_t * EDROOMpVarVStringDataBurst, CEDROOMPOOLCDFrame & EDROOMpPoolCDFrame, CEDROOMPOOLCDSignal & EDROOMpPoolCDSignal ):

	EDROOMcomponent(act)
	,Msg(EDROOMcomponent.Msg)
	,MsgBack(EDROOMcomponent.MsgBack)
	,SsiFromComponent(EDROOMcomponent.SsiFromComponent)
	, VByteNumber ( EDROOMpVarVByteNumber )
	, VMessageCompleted ( EDROOMpVarVMessageCompleted )
	, VStringDataBurst ( EDROOMpVarVStringDataBurst )
	, EDROOMPoolCDFrame ( EDROOMpPoolCDFrame )
	, EDROOMPoolCDSignal ( EDROOMpPoolCDSignal )
 {

}

CASsiDriver::EDROOMTopContext::EDROOMTopContext ( EDROOMTopContext &contex ):

	EDROOMcomponent(contex.EDROOMcomponent),
	Msg(contex.Msg),
	MsgBack(contex.MsgBack)
	,SsiFromComponent(contex.SsiFromComponent)
	, VByteNumber ( contex.VByteNumber )
	, VMessageCompleted ( contex.VMessageCompleted )
	, VStringDataBurst ( contex.VStringDataBurst )
	, EDROOMPoolCDFrame ( contex.EDROOMPoolCDFrame )
	, EDROOMPoolCDSignal ( contex.EDROOMPoolCDSignal )
 {

}

	// EDROOMSearchContextTrans********************************************

bool CASsiDriver::EDROOMTopContext::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 switch(Msg->signal){

		 case ( EDROOMSignalDestroy ): 

			 edroomValidMsg=true;
			 edroomCurrentTrans.distanceToContext = 0 ;
			 edroomCurrentTrans.localId = -1 ;
			 break;

	}

	return(edroomValidMsg);

}

	// Funciones Definidas por el usuario  ****************************

void	CASsiDriver::EDROOMTopContext::FBuildUpFrame()

{	
 uint8_t i;
	VMessageCompleted=false;
	
	if (SIGNAL_FRAME_LENGTH==VByteNumber)
	{
 
		CDSignal * ap_CDSignal = EDROOMPoolCDSignal.AllocData();
	
		// Complete Data 
	
		for (i=0;i<SIGNAL_FRAME_LENGTH;i++)
		{
			ap_CDSignal->signalFrame[i]=VStringDataBurst[i];
		}
	
		// send new Msg
	
		SsiFromComponent.send(SSignalFrame, EDROOMprioNormal, ap_CDSignal, &EDROOMPoolCDSignal);
	}
	else if (DATA_FRAME_LENGTH==VByteNumber)
	{
 
		CDFrame * ap_CDFrame = EDROOMPoolCDFrame.AllocData();
	
		// Complete Data 
	
			for (i=0;i<DATA_FRAME_LENGTH;i++)
		{
			ap_CDFrame->dataFrame[i]=VStringDataBurst[i];
		}
	
		// send new Msg
	
		SsiFromComponent.send(SDataFrame, EDROOMprioNormal, ap_CDFrame, &EDROOMPoolCDFrame);
	
	}
	else
	{
		//ERROR
	}
	VByteNumber=0;
}



void	CASsiDriver::EDROOMTopContext::FCheckBytesReceived()

{
 if ((VByteNumber==SIGNAL_FRAME_LENGTH) &&
		(ssi_link_layer_check_signal_frame_crc(VStringDataBurst)))
		{
					VMessageCompleted=true;
		}
		else if (VByteNumber==DATA_FRAME_LENGTH)
 
		{
 
			if	(ssi_link_layer_check_data_frame_crc(VStringDataBurst))
			{
					VMessageCompleted=true;
			}
			else
			{
				VByteNumber=-1;
			}
 
		}
}



void	CASsiDriver::EDROOMTopContext::FGetData()

{
	while (bufferOfDevices[0].bytesWritten && !(VMessageCompleted))
	{
		VStringDataBurst[VByteNumber]=bufferOfDevices[0].buffer[bufferOfDevices[0].readIndex];
		bufferOfDevices[0].readIndex++;
		bufferOfDevices[0].readIndex%=BUFFER_SIZE;//TODO: cambiar macro
 
		VByteNumber++;
 
		Pr_IRQManager::DisableIRQ(2);
		bufferOfDevices[0].bytesWritten--;
		Pr_IRQManager::EnableIRQ(2);
		printf("\n%d\n",VByteNumber);
		FCheckBytesReceived();
	}
}



void	CASsiDriver::EDROOMTopContext::FInit()

{
 
}



void	CASsiDriver::EDROOMTopContext::FSendDataFrameToGround()

{
 uint8_t i=0;
	CDFrame & varCDFrame = *(CDFrame *)Msg->data;
 
	for (i=0;i<DATA_FRAME_LENGTH;i++)
	{
		ssi_uart_dev_putchar(varCDFrame.dataFrame[i]);
	}
}



void	CASsiDriver::EDROOMTopContext::FSendSignalFrameToGround()

{
 uint8_t i=0;
	CDFrame & varCDDataFrame = *(CDFrame *)Msg->data;
 
	for (i=0;i<DATA_FRAME_LENGTH;i++)
	{
		ssi_uart_dev_putchar(varCDDataFrame.dataFrame[i]);
	}
}



void	CASsiDriver::EDROOMTopContext::FWaitToResponse()

{
//	while (!(VMessageCompleted) || VByteNumber!=-1)
//	{
//		FGetData();
//	}
//
//	if (VMessageCompleted)
//	{
//		FBuildUpFrame();
//	}
//	else
//	{
//		VByteNumber=0;
//	}
}



	//*****Pools

	//CEDROOMPOOLCDFrame

CASsiDriver::EDROOMTopContext::CEDROOMPOOLCDFrame::CEDROOMPOOLCDFrame(unsigned int elemCount, CDFrame* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDFrame)){;}

CDFrame *	CASsiDriver::EDROOMTopContext::CEDROOMPOOLCDFrame::AllocData(){
	return(CDFrame*)CEDROOMProtectedMemoryPool::AllocData();
}

	//CEDROOMPOOLCDSignal

CASsiDriver::EDROOMTopContext::CEDROOMPOOLCDSignal::CEDROOMPOOLCDSignal(unsigned int elemCount, CDSignal* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDSignal)){;}

CDSignal *	CASsiDriver::EDROOMTopContext::CEDROOMPOOLCDSignal::AllocData(){
	return(CDSignal*)CEDROOMProtectedMemoryPool::AllocData();
}



// ***********************************************************************

// class EDROOMTopState

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CASsiDriver::EDROOMTopState::EDROOMTopState (CASsiDriver &act, CEDROOMMemory *pEDROOMMemory  ):
	  EDROOMTopContext( act , VByteNumber, VMessageCompleted, VStringDataBurst,EDROOMPoolCDFrame,EDROOMPoolCDSignal )
	, VByteNumber ( 0 )
	, VMessageCompleted ( false )
	, EDROOMPoolCDFrame ( 10, pEDROOMMemory->poolCDFrame, pEDROOMMemory->poolMarkCDFrame)
	, EDROOMPoolCDSignal ( 10, pEDROOMMemory->poolCDSignal, pEDROOMMemory->poolMarkCDSignal)
{

}

	// EDROOMBehaviour**********************************************

void CASsiDriver::EDROOMTopState::EDROOMBehaviour(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans = EDROOMIllegada();

	do{

		switch(edroomCurrentTrans.localId){

			case(Init):
				FInit();
				edroomNextState = Listening;
				break;
			case(SendData):
				FSendDataFrameToGround();
				edroomNextState = Listening;
				break;
			case(SendSignal):
				FSendSignalFrameToGround();
				edroomNextState = Listening;
				break;
		}

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(I):
				edroomCurrentTrans=EDROOMIllegada();
				break;

			case(Listening):
				FWaitToResponse();
				edroomCurrentTrans=EDROOMListeningllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

	}while(Msg->signal != EDROOMSignalDestroy);

}



	// Inicio**********************************************

void CASsiDriver::EDROOMTopState::EDROOMInicio(){

edroomCurrentState=I;

}



//	 ***********************************************************************

//	 llegada SubEstado I

//	 ***********************************************************************



TEDROOMTransId CASsiDriver::EDROOMTopState::EDROOMIllegada(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans.localId = Init;
	edroomCurrentTrans.distanceToContext = 0;
	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, 0);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja Listening

	// ***********************************************************************



TEDROOMTransId CASsiDriver::EDROOMTopState::EDROOMListeningllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (SDataFrame): 

				 if ( *Msg->GetPInterface() == SsiFromComponent) {

					edroomCurrentTrans.localId= SendData;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (SSignalFrame): 

				 if ( *Msg->GetPInterface() == SsiFromComponent) {

					edroomCurrentTrans.localId= SendSignal;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



